package cn.pconline.security2.authorization;

import cn.pconline.activity.cache.CacheClient;
import cn.pconline.activity.util.EnvUtils;
import cn.pconline.censor.client.repository.DecodeUtils;
import cn.pconline.censor.client.repository.DecodeUtils.Type;
import cn.pconline.censor.client.repository.EncodeBuilder;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;

class AdminSessionRepository {
	public static final String SECURITY_SESSION_KEY_PREFIX = "security-session-";
	public static final String SECURITY_USER_KEY_PREFIX = "security-user-";
	SimpleJdbcTemplate simpleJdbcTemplate;
	CacheClient cacheClient;

	public void setSimpleJdbcTemplate(SimpleJdbcTemplate simpleJdbcTemplate) {
		this.simpleJdbcTemplate = simpleJdbcTemplate;
	}

	public void setCacheClient(CacheClient cacheClient) {
		this.cacheClient = cacheClient;
	}

	public static AdminSessionRepository instnace() {
		return (AdminSessionRepository)EnvUtils.getEnv().getApplicationContext().getBean("adminSessionRepository");
	}

	public AdminSession find(String sessionId) {
		AdminSession session = getFromCache(sessionId);
		if (session == null) {
			session = findFromDb(sessionId);
            if(session != null){
                putToCache(session);
            }
		}
		return session;
	}

	public void removeSession(String sessionId) {
		String key = SECURITY_SESSION_KEY_PREFIX + sessionId;
		AdminSession session = getFromCache(sessionId);
//		cacheClient.delete(key);
		simpleJdbcTemplate.update("delete from sec_session where sessionid = ?", sessionId);
		if (session != null) {
			String key2 = SECURITY_USER_KEY_PREFIX + session.getUserId();
//			cacheClient.delete(key2);
		}
	}

	public AdminSession findFromDb(final String sessionId) {
		return simpleJdbcTemplate.queryForObject("select * from sec_session where sessionid = ? ",
				new ParameterizedRowMapper<AdminSession>() {
					@Override
					public AdminSession mapRow(ResultSet rs, int arg1) throws SQLException {
						AdminSession adminSession = new AdminSession();
						adminSession.setSessionId(sessionId);
						adminSession.setUserId(rs.getString("userid"));
						adminSession.setApplication(rs.getString("application"));
						adminSession.setIp(rs.getString("ip"));
						adminSession.setLoginTime(rs.getTimestamp("logintime"));
						return adminSession;
					}
				}, sessionId);
	}

	public AdminSession getFromCache(String sessionId) {
		String key = SECURITY_SESSION_KEY_PREFIX + sessionId;
//		String value = (String)cacheClient.get(key);
        String value = null;
		if (value == null) {
			return null;
		}
		AdminSessionDecodeHandler handler = new AdminSessionDecodeHandler();
		DecodeUtils.decode(value, handler);
		return handler.getAdminSession();
	}

	public void putToCache(AdminSession session) {
		Date expiryAt = new Date(System.currentTimeMillis() + 1000 * 60 * 20);
		String key = SECURITY_SESSION_KEY_PREFIX + session.getSessionId();
//		cacheClient.set(key, encode(session), expiryAt);
		String key2 = SECURITY_USER_KEY_PREFIX + session.getUserId();
//		cacheClient.set(key2, "" + session.getSessionId(), expiryAt);
		
	}

	public void createSession(AdminSession adminSession) {
		simpleJdbcTemplate.update("insert into sec_session (sessionid, userid, ip, logintime, application) values (?,?,?,?,?)",
				adminSession.getSessionId(),
				adminSession.getUserId(),
				adminSession.getIp(),
				adminSession.getLoginTime(),
				adminSession.getApplication());
	}

	static enum Field {
		sessionId,
		userId,
		ip,
		loginTime,
		application
	}

	String encode(AdminSession session) {
		EncodeBuilder eb = new EncodeBuilder();
		eb.append(Field.sessionId, session.getSessionId());
		eb.append(Field.userId, session.getUserId());
		eb.append(Field.ip, session.getIp());
		eb.append(Field.loginTime, session.getLoginTime().getTime());
		eb.append(Field.application, session.getApplication());
		return eb.toString();
	}

	static class AdminSessionDecodeHandler implements DecodeUtils.ItemHandler {
		AdminSession session = new AdminSession();
		public AdminSession getAdminSession() { return session; }

		@Override
		public void handle(String name, String value, Type type) {
			Field f = Field.valueOf(name);
			switch (f) {
				case sessionId: session.setSessionId(value); break;
				case userId:	session.setUserId(value); break;
				case ip:		session.setIp(value); break;
				case loginTime: session.setLoginTime(new Date(Long.parseLong(value))); break;
				case application: session.setApplication(value); break;
				default: break;
			}
		}
	}

}
